{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c8ae013b221b9bfe",
   "metadata": {},
   "source": [
    "NumPy 是 Python 中用于科学计算的基础库，提供了高性能的多维数组对象和工具。本教程将带你快速掌握 NumPy 的核心功能。"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 标量、向量、矩阵\n",
    "标量是单个数字。\n",
    "\n",
    "向量是一串数字（代表一个样本的特征或一组参数）。\n",
    "\n",
    "矩阵是一张数字表格（代表所有样本的特征集合）。"
   ],
   "id": "7fbf759b9caab255"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T01:09:47.132154Z",
     "start_time": "2025-06-15T01:09:47.127396Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 行向量\n",
    "a = [1, 2, 3, 4]\n",
    "\n",
    "# 列向量\n",
    "b = [[1], [2], [3], [4]]"
   ],
   "id": "8fdc8ca53c137377",
   "outputs": [],
   "execution_count": 15
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "画一个坐标轴来表示一个向量\n",
    "[3, 2]"
   ],
   "id": "301595a7032f0160"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T01:02:22.273735Z",
     "start_time": "2025-06-15T01:02:12.614157Z"
    }
   },
   "cell_type": "code",
   "source": "!pip install matplotlib",
   "id": "98e63864f1715d2b",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting matplotlib\r\n",
      "  Downloading matplotlib-3.10.3-cp310-cp310-macosx_11_0_arm64.whl.metadata (11 kB)\r\n",
      "Collecting contourpy>=1.0.1 (from matplotlib)\r\n",
      "  Using cached contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl.metadata (5.5 kB)\r\n",
      "Collecting cycler>=0.10 (from matplotlib)\r\n",
      "  Using cached cycler-0.12.1-py3-none-any.whl.metadata (3.8 kB)\r\n",
      "Collecting fonttools>=4.22.0 (from matplotlib)\r\n",
      "  Downloading fonttools-4.58.4-cp310-cp310-macosx_10_9_universal2.whl.metadata (106 kB)\r\n",
      "Collecting kiwisolver>=1.3.1 (from matplotlib)\r\n",
      "  Using cached kiwisolver-1.4.8-cp310-cp310-macosx_11_0_arm64.whl.metadata (6.2 kB)\r\n",
      "Requirement already satisfied: numpy>=1.23 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from matplotlib) (2.2.6)\r\n",
      "Requirement already satisfied: packaging>=20.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from matplotlib) (25.0)\r\n",
      "Collecting pillow>=8 (from matplotlib)\r\n",
      "  Using cached pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl.metadata (8.9 kB)\r\n",
      "Collecting pyparsing>=2.3.1 (from matplotlib)\r\n",
      "  Using cached pyparsing-3.2.3-py3-none-any.whl.metadata (5.0 kB)\r\n",
      "Requirement already satisfied: python-dateutil>=2.7 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from matplotlib) (2.9.0.post0)\r\n",
      "Requirement already satisfied: six>=1.5 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib) (1.17.0)\r\n",
      "Downloading matplotlib-3.10.3-cp310-cp310-macosx_11_0_arm64.whl (8.0 MB)\r\n",
      "\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m8.0/8.0 MB\u001B[0m \u001B[31m8.6 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m00:01\u001B[0m00:01\u001B[0m\r\n",
      "\u001B[?25hUsing cached contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl (253 kB)\r\n",
      "Using cached cycler-0.12.1-py3-none-any.whl (8.3 kB)\r\n",
      "Downloading fonttools-4.58.4-cp310-cp310-macosx_10_9_universal2.whl (2.7 MB)\r\n",
      "\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m2.7/2.7 MB\u001B[0m \u001B[31m44.3 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n",
      "\u001B[?25hUsing cached kiwisolver-1.4.8-cp310-cp310-macosx_11_0_arm64.whl (65 kB)\r\n",
      "Using cached pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl (3.0 MB)\r\n",
      "Using cached pyparsing-3.2.3-py3-none-any.whl (111 kB)\r\n",
      "Installing collected packages: pyparsing, pillow, kiwisolver, fonttools, cycler, contourpy, matplotlib\r\n",
      "\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m7/7\u001B[0m [matplotlib]7\u001B[0m [matplotlib]\r\n",
      "\u001B[1A\u001B[2KSuccessfully installed contourpy-1.3.2 cycler-0.12.1 fonttools-4.58.4 kiwisolver-1.4.8 matplotlib-3.10.3 pillow-11.2.1 pyparsing-3.2.3\r\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T01:52:13.914021Z",
     "start_time": "2025-06-15T01:52:13.859791Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 创建二维坐标系\n",
    "plt.figure(figsize=(6, 6))\n",
    "ax = plt.gca()\n",
    "\n",
    "# 定义要展示的向量\n",
    "vector = np.array([3, 2])  # 向量 [3, 2]\n",
    "\n",
    "# 绘制从原点(0,0)到(3,2)的向量箭头\n",
    "ax.quiver(0, 0, vector[0], vector[1],\n",
    "          angles='xy', scale_units='xy', scale=1,\n",
    "          color='blue', width=0.01, headwidth=8, headlength=10)\n",
    "\n",
    "# 标记向量终点和向量符号\n",
    "plt.scatter(vector[0], vector[1], color='red')  # 终点红点\n",
    "\n",
    "# 设置坐标轴范围和网格\n",
    "plt.xlim(0, 4)\n",
    "plt.ylim(0, 4)\n",
    "plt.grid(linestyle='--', alpha=0.7)\n",
    "\n",
    "# 添加原点标识\n",
    "plt.scatter(0, 0, color='black', s=50, label='原点')\n",
    "plt.text(0, -0.3, '(0,0)', fontsize=10)\n",
    "\n",
    "# 显示图形\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ],
   "id": "11d1e8b9d4e301e9",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 600x600 with 1 Axes>"
      ],
      "image/png": "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y52uNr9WvU1tb6pNmokWjv369XM+PwhtSuY86f9zc9DrKwhtiufYI7dHZtCyZctAtCmZ8+TmoG+g7vH7vU2xtkdrk/5dc+jbt2/d9/d7mxo79vXrRRYsyJYPP8yWBQuqpNX82fL3nd+3Y9T3htxcmX/dddLvgQckp7LStu/ZI/L226HqadIiI/J3RRDaVJXEedIhPVq4pf323OWXX+6MUZo9e3bMgklpF2HD4kg/1u3R6C8BfTXknvxI7olpbN/GRNve8Osms11PWGPbox1jotvdi61hDn5vU2OaapObg3t7LghtSnS7m0GQ2hQp3ja510CQ2pTodvcXUGPvke72/T325m7Tli0i2unw4Yc58uGH+qfIhg31WiXZcopskHZymHwuWWK/mLOqq52CKVeLJndM0ymnSG4CGfj956mx3xV+b1NuEucp2vdutqJJq7orrrhCXn75ZZk5c6YcddRRTX7O4MGD5e2333Zu5bl05p1uBwDg669FioutMHJfK1Y0/XnVkiNXykPykpwnNbXFcx334wcfDNUgcHgroaJJlxuYOnWqvPLKK85aTe64JL0HqvcS1ciRI+Wwww5zxiWpK6+8Uk499VS57777ZNiwYfL888879yyffPLJhA+2seo2TLT9ep+YHMiBDAw5+C8HvZuiw1Dmz/+mQNLhKnoXLRn/zP2xfDrpJen60JWSvX69dH3tNcnWnjftYdKC6cc/lrDx0/XgJS/an9CYJrcbvKFnn31WLrzwQufvQ4YMkSOPPFKmTJlSb3HLG264QT799FM55phj5O6775azzz477oPk2XMA4D/62+Wzz+oXSHrLLZXjc2+9VeSGG2qrsX//2+7hdewoomOY6GEKta0e1A6+emDvV199VTcQPIx0wJvORNDZil7cq/ULciADFzlkVg5ffWUFUmSRFGW+T0qccILIe+/peJfMyiHdyMHoQHBdEintA8HTxQf1neft16mb5EAOZGDIIX056CzyRYusMHKLpJUrm+3bi44I+cMfvimYFNeDIQfjRft9VTQBAJqf3vn66KP6BdKSJTprL33HdM89It/+dvq+P8KJogkAUEf/cb52bf0CacECkRiPGG12Z56pawWm+ygQRr4a06TPkdE/w0pPld6b1QyiDcoPA3IgAxc57H8OmzZ9Uxy5f0Ys+Jxx9FeAPu+9sSUCuR4MORjNQFcf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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 52
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 向量模长\n",
    "向量的**大小**（也称为**模长**或**范数**）表示向量的长度或强度。在数学和机器学习中，这是向量的基本属性之一。以下是计算向量大小的详细方法：\n",
    "\n",
    "## 基本公式\n",
    "\n",
    "对于一个 n 维向量 $\\mathbf{v} = [v_1, v_2, \\dots, v_n]$，其大小计算公式为：\n",
    "\n",
    "$\\|\\mathbf{v}\\| = \\sqrt{v_1^2 + v_2^2 + \\cdots + v_n^2}$"
   ],
   "id": "d884a322ff5a9068"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## L0范数、L1范数、L2范数\n",
    "L0范数（Zero Norm）是向量中非零元素个数。\n",
    "\n",
    "L1范数（Manhattan Norm）是向量中元素绝对值之和。\n",
    "\n",
    "L2范数（Euclidean Norm）是向量中元素平方和然后求平方根，也就是向量模长。"
   ],
   "id": "9389c1a535c2bace"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T01:56:38.192415Z",
     "start_time": "2025-06-15T01:56:38.188895Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 计算向量的大小\n",
    "v = [3, 4]\n",
    "squared_sum = sum(x ** 2 for x in v)\n",
    "result = squared_sum ** 0.5\n",
    "print(result)"
   ],
   "id": "dccbbf40a17fcd72",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5.0\n"
     ]
    }
   ],
   "execution_count": 54
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 模长的几何意义-勾股定理\n",
    "勾股定理是指直接三角形的斜边平方等于直角边平方之和。"
   ],
   "id": "2d2295dc74f39dce"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 特征向量\n",
    "机器学习中，特征向量是指一个样本的属性向量，用于描述样本的属性特征，比如一个人的特征向量可能为：[身高，体重，年龄]。\n",
    "\n",
    "比如[170, 140, 35]，这就表示某一个人的特征，这个向量叫做特征向量"
   ],
   "id": "5054eac93ec507a8"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 矩阵\n",
    "矩阵由向量组成的。\n",
    "\n",
    "一个 $ 2 \\times 3 $ 的矩阵：\n",
    "$\n",
    "A = \\begin{bmatrix}\n",
    "a_{11} & a_{12} & a_{13} \\\\\n",
    "a_{21} & a_{22} & a_{23}\n",
    "\\end{bmatrix}\n",
    "$"
   ],
   "id": "97deeebda27b14ad"
  },
  {
   "cell_type": "markdown",
   "id": "dc52f65d171997a3",
   "metadata": {},
   "source": [
    "## 安装 NumPy"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22465f4580997d89",
   "metadata": {},
   "source": [
    "如果你还没有安装 NumPy，可以使用 pip 安装："
   ]
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:01:36.453886Z",
     "start_time": "2025-06-15T02:01:35.851963Z"
    }
   },
   "cell_type": "code",
   "source": "!pip install numpy",
   "id": "9aaad4924b12f824",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: numpy in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (2.2.6)\r\n"
     ]
    }
   ],
   "execution_count": 55
  },
  {
   "cell_type": "markdown",
   "id": "27eda0c1d84cef4",
   "metadata": {},
   "source": "## 导入Numpy"
  },
  {
   "cell_type": "code",
   "id": "90b9fa988361af95",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-10T12:38:29.682754Z",
     "start_time": "2025-06-10T12:38:29.680535Z"
    }
   },
   "source": [
    "import numpy as np"
   ],
   "outputs": [],
   "execution_count": 38
  },
  {
   "cell_type": "markdown",
   "id": "b2280723a1698591",
   "metadata": {},
   "source": "### 创建数组（向量）"
  },
  {
   "cell_type": "code",
   "id": "d993108622c15ff1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:02:24.641210Z",
     "start_time": "2025-06-15T02:02:24.634703Z"
    }
   },
   "source": [
    "# 向量\n",
    "a = np.array([1, 2, 3, 4, 5])\n",
    "print(a)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 4 5]\n"
     ]
    }
   ],
   "execution_count": 56
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:03:10.627682Z",
     "start_time": "2025-06-15T02:03:10.624427Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 矩阵\n",
    "b = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "print(b)"
   ],
   "id": "eeeabdf296c4f4a6",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n"
     ]
    }
   ],
   "execution_count": 58
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 区别",
   "id": "b5b091ceaacc81f9"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:03:50.251592Z",
     "start_time": "2025-06-15T02:03:50.245133Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# Python中的数据类型可以混合\n",
    "list_mixed = [1, \"hello\", 3.14]\n",
    "print(list_mixed)"
   ],
   "id": "a0d8b8ded63823d1",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 'hello', 3.14]\n"
     ]
    }
   ],
   "execution_count": 59
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:05:07.441352Z",
     "start_time": "2025-06-15T02:05:07.437332Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# NumPy中的数据类型需要统一，不同会进行类型转换\n",
    "import numpy as np\n",
    "\n",
    "arr = np.array([1, 2.5, 3])\n",
    "print(arr)"
   ],
   "id": "bd3d0e4d6c4d4f54",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.  2.5 3. ]\n"
     ]
    }
   ],
   "execution_count": 62
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:05:53.841513Z",
     "start_time": "2025-06-15T02:05:53.837551Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# NumPy向量化加法（高效）\n",
    "arr1 = np.array([1, 2, 3])\n",
    "arr2 = np.array([4, 5, 6])\n",
    "result = arr1 + arr2\n",
    "print(result)"
   ],
   "id": "f1ccf7add64dc627",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5 7 9]\n"
     ]
    }
   ],
   "execution_count": 64
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:07:08.199293Z",
     "start_time": "2025-06-15T02:07:08.192650Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 列表需循环（低效）\n",
    "list1 = [1, 2, 3]\n",
    "list2 = [4, 5, 6]\n",
    "# result = list1 + list2\n",
    "# print(result)\n",
    "result = [a + b for a, b in zip(list1, list2)]\n",
    "print(result)"
   ],
   "id": "8d0f9e59c34b63c0",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 7, 9]\n"
     ]
    }
   ],
   "execution_count": 65
  },
  {
   "cell_type": "markdown",
   "id": "d61b9a632d8d10cd",
   "metadata": {},
   "source": "## 特殊矩阵"
  },
  {
   "cell_type": "code",
   "id": "ae47a048c839fc1e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:09:58.110648Z",
     "start_time": "2025-06-15T02:09:58.103466Z"
    }
   },
   "source": [
    "# 全零矩阵\n",
    "zeros = np.zeros(shape=(2, 3), dtype=np.int32)  # 2行3列\n",
    "print(zeros)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 0 0]\n",
      " [0 0 0]]\n"
     ]
    }
   ],
   "execution_count": 69
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:10:10.076345Z",
     "start_time": "2025-06-15T02:10:10.073775Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 全1矩阵\n",
    "ones = np.ones((3, 2))  # 3行2列\n",
    "print(ones)"
   ],
   "id": "4f4ae984208fefcb",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1.]\n",
      " [1. 1.]\n",
      " [1. 1.]]\n"
     ]
    }
   ],
   "execution_count": 70
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:10:30.946809Z",
     "start_time": "2025-06-15T02:10:29.719749Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 随机数组\n",
    "random_arr = np.random.random((2, 2))  # 2x2的随机数组，值在0-1之间\n",
    "print(random_arr)"
   ],
   "id": "b1da8bb64b36a6d6",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.70857383 0.46645398]\n",
      " [0.86464547 0.4666924 ]]\n"
     ]
    }
   ],
   "execution_count": 71
  },
  {
   "cell_type": "markdown",
   "id": "d43d956f0d74600c",
   "metadata": {},
   "source": "## 矩阵属性"
  },
  {
   "cell_type": "code",
   "id": "7e78b834e3d1c513",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:11:56.502190Z",
     "start_time": "2025-06-15T02:11:56.496181Z"
    }
   },
   "source": [
    "arr = np.array([[1, 2, 3],[4, 5, 6]])\n",
    "\n",
    "print(arr.shape)  # 矩阵形状\n",
    "print(arr.ndim)  # 矩阵维度\n",
    "print(arr.size)  # 矩阵元素总数"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2, 3)\n",
      "2\n",
      "6\n"
     ]
    }
   ],
   "execution_count": 74
  },
  {
   "cell_type": "markdown",
   "id": "4d20df03de2cbf25",
   "metadata": {},
   "source": [
    "## 索引和切片"
   ]
  },
  {
   "cell_type": "code",
   "id": "d61e62b8cde8aa1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:12:24.559688Z",
     "start_time": "2025-06-15T02:12:24.555233Z"
    }
   },
   "source": [
    "arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\n",
    "\n",
    "# 索引\n",
    "print(arr[0])  # 第一个元素\n",
    "print(arr[-1])  # 最后一个元素\n",
    "\n",
    "# 切片\n",
    "print(arr[1:5])  # 索引1到4的元素\n",
    "print(arr[::2])  # 每隔一个元素取一个"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "9\n",
      "[1 2 3 4]\n",
      "[0 2 4 6 8]\n"
     ]
    }
   ],
   "execution_count": 76
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:14:34.967510Z",
     "start_time": "2025-06-15T02:14:34.962536Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 矩阵索引\n",
    "arr2d = np.array([[1, 2, 3],\n",
    "                  [4, 5, 6],\n",
    "                  [7, 8, 9]])\n",
    "print(arr2d[1, 2])  # 第二行第三列的元素\n",
    "print(arr2d[:, 1])  # 所有行的第二列"
   ],
   "id": "65b929e093384ca9",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n",
      "[2 5 8]\n"
     ]
    }
   ],
   "execution_count": 79
  },
  {
   "cell_type": "markdown",
   "id": "6a6faaed3bdc2b72",
   "metadata": {},
   "source": [
    "## 形状操作"
   ]
  },
  {
   "cell_type": "code",
   "id": "30e86d2fa7b0b297",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:19:51.414824Z",
     "start_time": "2025-06-15T02:19:51.411461Z"
    }
   },
   "source": [
    "arr = np.arange(6)\n",
    "print(arr)\n",
    "\n",
    "# 改变形状\n",
    "arr2 = arr.reshape(2, 3)\n",
    "print(arr2)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4 5]\n",
      "[[0 1 2]\n",
      " [3 4 5]]\n"
     ]
    }
   ],
   "execution_count": 88
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:20:02.752045Z",
     "start_time": "2025-06-15T02:20:02.748342Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 展平，降维\n",
    "arr_flat = arr2.flatten()\n",
    "print(arr_flat)"
   ],
   "id": "8a2cade3480a33ec",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4 5]\n"
     ]
    }
   ],
   "execution_count": 89
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:20:54.632482Z",
     "start_time": "2025-06-15T02:20:54.627786Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 转置\n",
    "print((arr2))\n",
    "arr_t = arr2.T\n",
    "print(arr_t)"
   ],
   "id": "49e831780724a5d2",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2]\n",
      " [3 4 5]]\n",
      "[[0 3]\n",
      " [1 4]\n",
      " [2 5]]\n"
     ]
    }
   ],
   "execution_count": 91
  },
  {
   "cell_type": "markdown",
   "id": "34904365b5ccc00c",
   "metadata": {},
   "source": [
    "## 数学运算"
   ]
  },
  {
   "cell_type": "code",
   "id": "ba5214b382a976bb",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:22:16.884387Z",
     "start_time": "2025-06-15T02:22:16.882390Z"
    }
   },
   "source": [
    "a = np.array([1, 2, 3])\n",
    "b = np.array([4, 5, 6])"
   ],
   "outputs": [],
   "execution_count": 99
  },
  {
   "cell_type": "code",
   "id": "80a3834f7ae6dd2a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:22:18.005737Z",
     "start_time": "2025-06-15T02:22:18.001598Z"
    }
   },
   "source": [
    "# 元素级运算\n",
    "print(a + b)  # 加法\n",
    "print(a * b)  # 乘法"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5 7 9]\n",
      "[ 4 10 18]\n"
     ]
    }
   ],
   "execution_count": 100
  },
  {
   "cell_type": "code",
   "id": "11ff3f80846df69a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:26:54.569466Z",
     "start_time": "2025-06-15T02:26:54.565043Z"
    }
   },
   "source": [
    "# 矩阵乘法\n",
    "# 2*3   3*2   --> 2*2\n",
    "A = np.array([[1, 2, 3],\n",
    "              [4, 5, 6]])\n",
    "B = np.array([[7, 8],\n",
    "              [9, 10],\n",
    "              [11, 12]])\n",
    "print(A)\n",
    "print(B)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n",
      "[[ 7  8]\n",
      " [ 9 10]\n",
      " [11 12]]\n"
     ]
    }
   ],
   "execution_count": 106
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:26:56.094460Z",
     "start_time": "2025-06-15T02:26:56.090775Z"
    }
   },
   "cell_type": "code",
   "source": "print(np.dot(A, B))  # 矩阵乘法",
   "id": "a26b935d18000318",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 58  64]\n",
      " [139 154]]\n"
     ]
    }
   ],
   "execution_count": 107
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:27:03.583905Z",
     "start_time": "2025-06-15T02:27:03.579980Z"
    }
   },
   "cell_type": "code",
   "source": "print(A @ B)  # 矩阵乘法",
   "id": "772a7b8ad05b1e25",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 58  64]\n",
      " [139 154]]\n"
     ]
    }
   ],
   "execution_count": 108
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "矩阵乘法就是，结果矩阵C中的每个元素 C[i][j] 是矩阵A的第i行与矩阵B的第j列对应元素的乘积之和",
   "id": "3c8894f0823fc399"
  },
  {
   "cell_type": "code",
   "id": "fff4d9026a23d562",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:28:55.968572Z",
     "start_time": "2025-06-15T02:28:55.962976Z"
    }
   },
   "source": [
    "# 统计运算\n",
    "arr = np.array([[1, 2],\n",
    "                [3, 4]])\n",
    "print(np.sum(arr))  # 所有元素和\n",
    "print(np.sum(arr, axis=0))  # 列和\n",
    "print(np.sum(arr, axis=1))  # 行和\n",
    "print(np.mean(arr))  # 平均值\n",
    "print(np.max(arr, axis=0))  # 最大值\n",
    "print(np.min(arr))  # 最小值"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n",
      "[4 6]\n",
      "[3 7]\n",
      "2.5\n",
      "[3 4]\n",
      "1\n"
     ]
    }
   ],
   "execution_count": 114
  },
  {
   "cell_type": "markdown",
   "id": "1028644855f31f67",
   "metadata": {},
   "source": "## 广播机制"
  },
  {
   "cell_type": "code",
   "id": "b56e9e97f84fb753",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:29:34.738317Z",
     "start_time": "2025-06-15T02:29:34.735917Z"
    }
   },
   "source": [
    "a = np.array([[1, 2, 3], [1, 2, 3]])\n",
    "b = 2\n",
    "print(a * b)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2 4 6]\n",
      " [2 4 6]]\n"
     ]
    }
   ],
   "execution_count": 116
  },
  {
   "cell_type": "markdown",
   "id": "6f98ff50133a4680",
   "metadata": {},
   "source": [
    "## 常用函数"
   ]
  },
  {
   "cell_type": "code",
   "id": "87e0f0bcfab26da4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:31:20.818732Z",
     "start_time": "2025-06-15T02:31:20.814725Z"
    }
   },
   "source": [
    "# 排序\n",
    "arr = np.array([3, 1, 4, 2, 5])\n",
    "print(np.sort(arr))\n",
    "\n",
    "# 唯一值\n",
    "arr = np.array([1, 2, 2, 3, 3, 3])\n",
    "print(np.unique(arr))\n",
    "\n",
    "# 条件筛选\n",
    "arr = np.array([[1, 2, 3, 4, 10],[1, 2, 3, 4, 5]])\n",
    "print(arr[arr > 3])  # 输出大于3的元素\n",
    "\n",
    "# where函数\n",
    "print(np.where(arr > 3, arr, 0))  # 大于3的元素保留，其他设为0"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 4 5]\n",
      "[1 2 3]\n",
      "[ 4 10  4  5]\n",
      "[[ 0  0  0  4 10]\n",
      " [ 0  0  0  4  5]]\n"
     ]
    }
   ],
   "execution_count": 126
  },
  {
   "cell_type": "markdown",
   "id": "7d4068968b3d8d14",
   "metadata": {},
   "source": [
    "## 性能对比"
   ]
  },
  {
   "cell_type": "code",
   "id": "7d9b418da942b41d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-15T02:31:51.497312Z",
     "start_time": "2025-06-15T02:31:51.440986Z"
    }
   },
   "source": [
    "import time\n",
    "\n",
    "size = 1000000\n",
    "\n",
    "# Python列表\n",
    "python_list = list(range(size))\n",
    "start = time.time()\n",
    "result = [x * 2 for x in python_list]\n",
    "print(\"Python列表耗时:\", time.time() - start)\n",
    "\n",
    "# NumPy数组\n",
    "numpy_arr = np.arange(size)\n",
    "start = time.time()\n",
    "result = numpy_arr * 2\n",
    "print(\"NumPy数组耗时:\", time.time() - start)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python列表耗时: 0.02912116050720215\n",
      "NumPy数组耗时: 0.00919198989868164\n"
     ]
    }
   ],
   "execution_count": 127
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
